﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

using RingControls.Extensions;

namespace RingControls
{
    internal class RingFigure
    {
        private LineSegment[] _lines = new LineSegment[2]
        {
            new LineSegment(), new LineSegment()
        };
        private ArcSegment[] _arcs = new ArcSegment[4]
        {
            new ArcSegment(), new ArcSegment(), new ArcSegment(), new ArcSegment()
        };
        private Path _path = null;
        private PathFigure _figure = null;

        internal void ApplyTo(Path path)
        {
            _figure = new PathFigure();
            _figure.Segments.Add(_lines[0]);
            _figure.Segments.Add(_arcs[0]);
            _figure.Segments.Add(_arcs[1]);
            _figure.Segments.Add(_lines[1]);
            _figure.Segments.Add(_arcs[2]);
            _figure.Segments.Add(_arcs[3]);

            var geometry = new PathGeometry();
            geometry.Figures.Add(_figure);

            path.Data = geometry;
            _path = path;
        }

        internal void Draw(double startRadian, double endRadian, Point center, double outerRadius, double innerRadius, bool clockwise)
        {
            // ArgSegment can't draw 360°. So the arc is devided in half;
            // (s + e) / 2. if s is larger than e, then (s + (2π - (s - e)) / 2).
            var halfRadian = ((startRadian < endRadian)
                ? ((endRadian + startRadian) / 2.0)
                : startRadian + (Math.PI - (startRadian - endRadian) / 2.0)).NormalizeRadian();

            _figure.StartPoint = RollPoint(center, startRadian, innerRadius);

            _lines[0].Point = RollPoint(center, startRadian, outerRadius);

            _arcs[0].Point = RollPoint(center, halfRadian, outerRadius);
            _arcs[0].Size = new Size(outerRadius, outerRadius);
            _arcs[0].SweepDirection = SweepDirection.Clockwise;
            _arcs[0].IsLargeArc = false;

            _arcs[1].Point = RollPoint(center, endRadian, outerRadius);
            _arcs[1].Size = new Size(outerRadius, outerRadius);
            _arcs[1].SweepDirection = SweepDirection.Clockwise;
            _arcs[1].IsLargeArc = false;

            _lines[1].Point = RollPoint(center, endRadian, innerRadius);

            _arcs[2].Point = RollPoint(center, halfRadian, innerRadius);
            _arcs[2].Size = new Size(innerRadius, innerRadius);
            _arcs[2].SweepDirection = SweepDirection.Counterclockwise;
            _arcs[2].IsLargeArc = false;

            _arcs[3].Point = RollPoint(center, startRadian, innerRadius);
            _arcs[3].Size = new Size(innerRadius, innerRadius);
            _arcs[3].SweepDirection = SweepDirection.Counterclockwise;
            _arcs[3].IsLargeArc = false;
        }

        public void Hide()
        {
            _path.Visibility = Visibility.Collapsed;
        }

        public void Show()
        {
            _path.Visibility = Visibility.Visible;
        }

        private Point RollPoint(Point center, double radian, double radius)
        {
            return new Point()
            {
                X = center.X + radius * Math.Cos(radian),
                Y = center.Y + radius * Math.Sin(radian),
            };
        }
    }
}
